<!DOCTYPE html>
<html>
  <head>
    <title>Stack Auth Dev Launchpad</title>
    <script src="./env-config.js"></script>
    <style>
      body {
        font-family: Arial, sans-serif;
        background-color: #e0f0e0;
        padding-left: 16px;
        padding-right: 16px;
      }

      .apps-container {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 16px;
      }
      
      .apps-container > a {
        border: 1px solid #8888;
        background-color: #fff;
        padding: 0px 4px 8px 4px;
        width: 120px;

        text-decoration: none;

        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 12px;

        position: relative;
      }

      .apps-container > a.important {
        background-color: #fee;
      }

      .apps-container > a.unimportant {
        opacity: 0.2;
      }

      .apps-container > a.unimportant:hover {
        opacity: 0.5;
      }

      .apps-container > a:hover {
        border-color: #888;
        transition: opacity 0.1s ease-in-out;
      }

      .apps-container > a > div > img {
        height: 68px;
      }

      .apps-container > a > .description {
        text-align: center;
        font-size: 12px;
        color: #888;
      }

      .apps-container > a > .port {
        padding-right: 0.5px;
        padding-top: 1px;
        align-self: flex-end;
        font-size: 12px;
        color: #888;
      }

      .apps-container > a > .hover-description {
        display: none;
        position: absolute;
        top: 100%;
        left: -1px;
        pointer-events: none;
        z-index: 1000;
        white-space: pre;
        background-color: #ffc;
        border: 1px solid #888;
        padding: 2px;
        color: #0008;
        font-size: 12px;
      }

      .apps-container > a:hover > .hover-description {
        display: block;
      }
    </style>
  </head>
  <body>
    <h1>Stack Auth Dev Launchpad</h1>
    <div class="apps-container"></div>
    <hr />
    <div class="apps-container"></div>
    <hr />
    <div class="apps-container"></div>

    <h2 style="margin-top: 64px;">Background services</h2>
    <ul class="background-services"></ul>
    <noscript>
      This page requires JavaScript.
    </noscript>
    <script>
      const derivePrefixFromLocation = () => {
        const port = window.location.port;
        if (!port || port.length < 2) return "81";
        return port.slice(0, -2);
      };
      const stackPortPrefix = window.NEXT_PUBLIC_STACK_PORT_PREFIX || derivePrefixFromLocation();
      window.NEXT_PUBLIC_STACK_PORT_PREFIX = stackPortPrefix;
      const withPrefix = (suffix) => `${stackPortPrefix}${suffix}`;

      // Depending on the port prefix, set the color to light grey (port 91), light purple (port 92), papyrus yellow (port 93), or default otherwise
      const color = {
        "91": "#f8f8f8",
        "92": "#fff8e0",
        "93": "#e0e0ff",
      }[stackPortPrefix] || undefined;
      document.body.style.backgroundColor = color;

      const backgroundServices = [
        { suffix: "28", label: "PostgreSQL" },
        { suffix: "29", label: "Inbucket SMTP" },
        { suffix: "30", label: "Inbucket POP3" },
        { suffix: "31", label: "OTel collector" },
        { suffix: "21", label: "S3 mock" },
        { suffix: "22", label: "Freestyle mock" },
        { suffix: "24", label: "LocalStack Gateway (AWS mock)" },
        { suffix: "25", label: "QStash mock" },
        { range: ["50", "99"], label: "Reserved for LocalStack (external services)" },
      ];

      const backgroundList = document.querySelector(".background-services");
      backgroundList.innerHTML = backgroundServices.map((service) => {
        const portText = service.range
          ? `${withPrefix(service.range[0])}-${withPrefix(service.range[1])}`
          : withPrefix(service.suffix);
        return `<li>${portText}: ${service.label}</li>`;
      }).join("");

      const apps = [
        {
          name: "Dashboard",
          portSuffix: "01",
          description: [
            "Src: ./apps/dashboard",
            "Prod: https://app.stack-auth.com",
          ],
          img: "https://www.svgrepo.com/show/507260/dashboard.svg",
          importance: 2,
        },
        {
          name: "Backend",
          portSuffix: "02",
          description: [
            "Src: ./apps/backend",
            "Prod: https://api.stack-auth.com",
          ],
          img: "https://www.svgrepo.com/show/340122/datastore.svg",
          importance: 2,
        },
        {
          name: "Demo app",
          portSuffix: "03",
          description: [
            "Src: ./examples/demo",
            "Prod: https://demo.stack-auth.com",
          ],
          importance: 2,
        },
        {
          name: "Docs",
          portSuffix: "04",
          description: [
            "Src: ./docs",
            "Prod: https://docs.stack-auth.com",
          ],
          img: "https://www.svgrepo.com/show/448400/docs.svg",
          importance: 2,
        },
        {
          name: "Inbucket",
          portSuffix: "05",
          img: "https://www.svgrepo.com/show/533176/at-sign.svg",
          importance: 1,
          description: [
            "Email mock",
          ],
        },
        {
          name: "Prisma Studio",
          portSuffix: "06",
          importance: 1,
          img: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS95TdAw63YPAPcUpvRl4imIf-VJ1sGHnEvbw&s",
          description: [
            "Database interface",
          ],
        },
        {
          name: "Jaeger UI (OTel)",
          portSuffix: "07",
          description: [
            "Performance & tracing",
          ],
          importance: 1,
          img: "https://www.jaegertracing.io/img/jaeger-icon-reverse-color.svg",
        },
        {
          name: "examples/docs-examples",
          portSuffix: "08",
          description: [
            "Src: ./examples/docs-examples",
          ],
        },
        {
          name: "examples/cjs-test",
          portSuffix: "10",
          description: [
            "Src: ./examples/cjs-test",
          ],
        },
        {
          name: "examples/e-commerce",
          portSuffix: "11",
          description: [
            "Src: ./examples/e-commerce",
          ],
        },
        {
          name: "examples/middleware",
          portSuffix: "12",
          description: [
            "Src: ./examples/middleware",
          ],
        },
        {
          name: "Svix server",
          portSuffix: "13",
          importance: 1,
          img: "",
          description: [
            "Webhooks",
          ],
        },
        {
          name: "OAuth mock server",
          portSuffix: "14",
          description: [
            "Src: ./apps/mock-oauth-server",
          ],
        },
        {
          name: "examples/supabase",
          portSuffix: "15",
          description: [
            "Src: ./examples/supabase",
          ],
        },
        {
          name: "PgHero",
          portSuffix: "16",
          description: [
            "For database performance analysis",
          ],
          importance: 1,
          img: "https://pghero.dokkuapp.com/assets/pghero-88a0d052.png",
        },
        {
          name: "PgAdmin",
          portSuffix: "17",
          description: [
            "For database administration",
          ],
          importance: 1,
          img: "https://www.w3schools.com/postgresql/screenshot_postgresql_pgadmin4_6.png",
        },
        {
          name: "Supabase Studio",
          portSuffix: "18",
          path: "/project/default/editor",
          description: [
            "For database administration",
          ],
          importance: 1,
          img: "https://cdn.prod.website-files.com/655b60964be1a1b36c746790/655b60964be1a1b36c746d41_646dfce3b9c4849f6e401bff_supabase-logo-icon_1.png",
        },
        {
          name: "JS example",
          portSuffix: "19",
          description: [
            "JavaScript example",
          ],
        },
        {
          name: "React example",
          portSuffix: "20",
          description: [
            "React example",
          ],
        },
        {
          name: "Convex example",
          portSuffix: "27",
          importance: 0,
          description: [
            "Convex example",
          ],
        },
        {
          name: "Lovable React 18 example",
          portSuffix: "32",
          importance: 0,
          description: [
            "Lovable React 18 example",
          ],
        },
      ];

      const appsContainers = document.querySelectorAll(".apps-container");
      for (let i = 0; i < appsContainers.length; i++) {
        const appContainer = appsContainers[i];
        const importance = appsContainers.length - i - 1;
        for (const app of apps) {
          if ((app.importance ?? 0) === importance) {
            // TODO escape HTML
            appContainer.innerHTML += `
              <a href="http://localhost:${withPrefix(app.portSuffix)}${app.path ?? ""}" target="_blank" rel="noopener noreferrer" class="${app.importance === 2 ? "important" : app.importance === 1 ? "" : "unimportant"}">
                <div class="port">:${withPrefix(app.portSuffix)}</div>
                <div>
                  <img src=${app.img || `//localhost:${withPrefix(app.portSuffix)}/favicon.ico`} />
                </div>
                <span class="description">${app.name}</span>
                ${app.description ? `<div class="hover-description">${app.description.join("\n")}</div>` : ""}
              </a>
            `;
          }
        }
      }
    </script>
  </body>
</html>
